home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 015a / srdisk12.zip / SRDISK.C < prev    next >
C/C++ Source or Header  |  1991-10-04  |  20KB  |  708 lines

  1. /*
  2. **      ReSizeable RAMDisk formatter
  3. **      Version 1.20
  4. **
  5. **      Compiled with Borland C++ 2.0
  6. **
  7. **      Released to PUBLIC DOMAIN by author Marko Kohtala 1991
  8. **
  9. **      Some documentation available in accompanying file SRDISK.DOC.
  10. **      If not, contact author by sending E-mail from
  11. **
  12. **              Internet, Bitnet etc. to 'mkohtala@niksula.hut.fi'
  13. **              CompuServe to '>INTERNET:mkohtala@niksula.hut.fi'
  14. **
  15. **      or by calling Airline QBBS, 24H, HST, V.32, V.42, MNP,
  16. **      +358-0-8725380, and leaving mail to me, Marko Kohtala.
  17. */
  18.  
  19. #define VERSION "1.20"
  20.  
  21. /* History
  22.  
  23. 1.00 09-06-91 Initial release
  24.  
  25. 1.10 06-09-91
  26.  
  27. - Added full support for multiple FATs. 1.00 had the /F switch, but no
  28.   support for it in formatter.
  29.  
  30. - Updated to IOCTL_msg versio 1.10 so that media byte is no longer used
  31.   to indicate the media change but to indicate the drive is RAM disk.
  32.  
  33. - Some minor fixes.
  34.  
  35. 1.20 04-10-1991
  36.  
  37. - Fixed name of program by adding the missing 'Re' to 'Sizeable'.
  38.  
  39. - Added 16 bit FAT support; more 'sizeable' disks that had over 4077
  40.   clusters were not operational. Due to DOS's inconsistent behaviour,
  41.   disks with over 4077 and under 4088 clusters (or over 65518, possible
  42.   with 128 byte clusters and 8M disk size) are avoided by making
  43.   clusters bigger.
  44.  
  45. - Added DOS lookalike disk formats via switch /F.
  46.  
  47. - The FAT number is now defined via switch /A instead of /F.
  48.  
  49. - The time of format is stored in volume label.
  50.  
  51. - Upgraded to IOCTL_msg version 1.20 which tells the type of memory used
  52.   by the driver.
  53.  
  54. - Disallow sectors greater than 512 bytes as DOS can not handle them
  55.   properly but rather crashes when it encounters them.
  56.  
  57. - Allow clusters up to 8 kilobytes.
  58.  
  59. - Enhanced help.
  60.  
  61. */
  62.  
  63. #include <stdlib.h>
  64. #include <stdio.h>
  65. #include <io.h>
  66. #include <dir.h>
  67. #include <dos.h>
  68. #include <string.h>
  69. #include <time.h>
  70.  
  71. /* IOCTL_msg exchanged with ramdrive (byte aligned) */
  72. #pragma option -a-
  73. #pragma pack(1)
  74. const struct IOCTL_msg_hdr_s {  /* Header of the structure for comparison */
  75.   unsigned short len;           /* The size of the structure */
  76.   char unused;                  /* A byte to make it look like boot sector */
  77.   char OEM[8];                  /* OEM and structure version number */
  78. };
  79.  
  80. struct IOCTL_msg_s {            /* The whole structure */
  81.   struct IOCTL_msg_hdr_s hdr;
  82.   unsigned short bytes_per_sector;
  83.   unsigned char sectors_per_cluster;
  84.   unsigned short reserved_sectors;
  85.   unsigned char FATs;           /* Number of FATs on disk */
  86.   unsigned short dir_entries;   /* Root directory entries */
  87.   unsigned short sectors;       /* Total number of sectors on disk */
  88.   unsigned char media;          /* Identifies the media (default 0xFA) */
  89.   unsigned short FAT_sectors;   /* Sectors in one copy of FAT */
  90.   unsigned short disk_size;     /* Disk size in kilobytes */
  91.   char volume[12];              /* This is returned in the Check Media call */
  92.   unsigned char RW_access;
  93.   signed char media_change;     /* -1 if media changed, 1 if not */
  94.   unsigned short open_files;    /* These last two are not accepted in the */
  95.   int (far *IO_entry)(void);    /* driver but must be sent anyway */
  96.   unsigned char memory_type;    /* Types of memory the driver uses */
  97. } IOCTL_msg;
  98.  
  99. #define READ_ACCESS  1  /* Bit masks for RW_access in IOCTL_msg_s */
  100. #define WRITE_ACCESS 2
  101.  
  102. #define XMS_MEMORY  1   /* Different memory types supported bit masks */
  103. #define EMS_MEMORY  2
  104. #define CONV_MEMORY 4
  105. #define BSW_MEMORY  8
  106. #define UNKNOWN_MEMORY 0xF0
  107.  
  108. #pragma pack()
  109. #pragma option -a
  110.  
  111. struct IOCTL_msg_hdr_s IOCTL_msg_hdr =
  112. {
  113.   sizeof (struct IOCTL_msg_s),
  114.   0x90,
  115.   "SRD 1.20"
  116. };
  117.  
  118. /* Variables possibly supplied in command line */
  119. int drive=0;
  120. int format_f=0;       /* Nonzero if new format given */
  121. int force_f=0;        /* Nonzero if ok to format */
  122. enum {same, set, clear} write_f = same;    /* Write protect flag */
  123. int disk_size=-1;     /* Size in kilobytes, -1 not set */
  124. int sector_size=-1;   /* Sector size, -1 not set */
  125. int cluster_size=-1;  /* Allocation unit size, -1 not set */
  126. int dir_entries=-1;   /* Directory entries in root directory, -1 not set */
  127. int FATs=-1;          /* FAT copies on the disk */
  128. int media=-1;         /* New media */
  129. int sec_per_track=9;  /* Sectors per track */
  130. int sides=1;          /* Sides on disk */
  131.  
  132. /*
  133. **  SYNTAX
  134. */
  135.  
  136. void print_syntax(void)
  137. {
  138.   fputs(
  139.   "Syntax:  SRDISK [<drive letter>[:]] [<size>] [/S:<sector size>]\n"
  140.   "\t\t[/C:<cluster size>] [/D:<dir entries>] [/A:<FAT copies>]\n"
  141.   "\t\t[/F:<DOS disk size>] [/W[-]] [/Y] [/?]\n\n"
  142.   "Anything inside [] is optional, the brackets must not be typed.\n"
  143.   "'<something>' must be replaced by what something tells.\n\n"
  144.   "<drive letter> specifies the drive that is the RAM disk.\n"
  145.   "<size> determines the disk size in kilobytes.\n"
  146.   "/S:<sector size> is a power of 2 in range from 128 to 512 bytes.\n"
  147.   "/C:<cluster size> is a power of 2 in range from 128 to 8192 bytes.\n"
  148.   "/D:<dir entries> is the maximum number of entries in the root directory.\n"
  149.   "/A:<FAT copies> number of File Allocation Tables on disk. 1 is enough.\n"
  150.   "/F:<DOS disk size> may be one of 160, 180, 320, 360, 720, 1200, 1440.\n"
  151.   "\tThe disk attributes (including media byte) will be set according\n"
  152.   "\tto the matching DOS disk format.\n"
  153.   "/W Write protect disk, /W- enables writes.\n"
  154.   "/Y Yes, to all queries and quiet mode for batch file operation.\n"
  155.   "/? This help.\n"
  156.   "\n", stderr);
  157. }
  158.  
  159. /*
  160. **  ERROR HANDLING FUNCTIONS
  161. */
  162.  
  163. void syntax(char *err)
  164. {
  165.   fprintf(stderr, "Syntax error: %s\n\n", err);
  166.   print_syntax();
  167.   exit(3);
  168. }
  169.  
  170. void fatal(char *err)
  171. {
  172.   fprintf(stderr, "Fatal error: %s\n\n", err);
  173.   exit(1);
  174. }
  175.  
  176. void error(char *err)
  177. {
  178.   fprintf(stderr, "Error: %s\n\n", err);
  179.   return;
  180. }
  181.  
  182. /*
  183. **  COMMAND LINE PARSER
  184. */
  185.  
  186. int parse_narg(char *argp, char **next)
  187. {
  188.   int res;
  189.   if (*argp == ':') argp++;
  190.   res = strtol(argp, next, 10);
  191.   if (argp == *next) return -1;
  192.   return res;
  193. }
  194.  
  195. int ispow2(int size)
  196. {
  197.   int cmp;
  198.   for (cmp = 128; cmp; cmp <<=1)
  199.     if (cmp == size) return 1;
  200.   return 0;
  201. }
  202.  
  203. void set_DOS_disk(int size)
  204. {
  205.   static struct {
  206.     int disk_size;
  207.     int media;
  208.     int cluster_size;
  209.     int dir_entries;
  210.     int sec_per_track;
  211.     int sides;
  212.   } dos_disk[] = {
  213.     {  160, 0xFE, 512,  64,  8, 1 },
  214.     {  180, 0xFC, 512,  64,  9, 1 },
  215.     {  320, 0xFF,1024, 112,  8, 2 },
  216.     {  360, 0xFD,1024, 112,  9, 2 },
  217.     {  720, 0xF9,1024, 112,  9, 2 },
  218.     { 1200, 0xF9, 512, 224, 15, 2 },
  219.     { 1440, 0xF0, 512, 224, 18, 2 },
  220.     {0}
  221.   };
  222.   int i;
  223.  
  224.   for (i=0; dos_disk[i].disk_size; i++)
  225.     if (dos_disk[i].disk_size == size) {
  226.       disk_size = size;
  227.       cluster_size = dos_disk[i].cluster_size;
  228.       dir_entries = dos_disk[i].dir_entries;
  229.       media = dos_disk[i].media;
  230.       sec_per_track = dos_disk[i].sec_per_track;
  231.       sides = dos_disk[i].sides;
  232.       FATs = 2;
  233.       sector_size = 512;
  234.       format_f++;
  235.       return;
  236.     }
  237.  
  238.   syntax("Unknown DOS disk size");
  239. }
  240.  
  241. void parse_cmdline(int argc, char *argv[])
  242. {
  243.   int arg;
  244.   char *argp;
  245.  
  246.   for(arg=1; arg < argc; arg++) {
  247.     argp = argv[arg];
  248.     while(*argp) {
  249.       if (*argp == '/' || *argp == '-') {
  250.         argp++;
  251.         switch(toupper(*argp++)) {
  252.         case '?':
  253.         case 'H':
  254.           print_syntax();
  255.           exit(0);
  256.         case 'W':
  257.           switch(*argp) {
  258.           case '-': argp++;
  259.                     write_f = clear;
  260.                     break;
  261.           case '+': argp++;
  262.           default:  write_f = set;
  263.           }
  264.           break;
  265.         case 'Y':
  266.           force_f++;
  267.           break;
  268.         case 'S': /* Sector size */
  269.           sector_size = parse_narg(argp, &argp);
  270.           if (!ispow2(sector_size) || sector_size > 512)
  271.             syntax("Invalid sector size");
  272.           format_f++;
  273.           break;
  274.         case 'C': /* Cluster size */
  275.           cluster_size = parse_narg(argp, &argp);
  276.           if (!ispow2(cluster_size) || cluster_size > 8192)
  277.             syntax("Invalid cluster size");
  278.           format_f++;
  279.           break;
  280.         case 'D': /* Directory entries */
  281.           dir_entries = parse_narg(argp, &argp);
  282.           if (dir_entries < -1 || !dir_entries || dir_entries == 1
  283.           || dir_entries > 1000)
  284.             syntax("Invalid number of directory entries");
  285.           format_f++;
  286.           break;
  287.         case 'A': /* FATs */
  288.           FATs = parse_narg(argp, &argp);
  289.           if (FATs < -1 || !FATs)
  290.             syntax("Invalid number of FAT copies");
  291.           format_f++;
  292.           break;
  293.         case 'F': /* DOS disk format */
  294.           disk_size = parse_narg(argp, &argp);
  295.           set_DOS_disk(disk_size);
  296.           break;
  297.         default:
  298.           syntax("Unknown switch");
  299.         }
  300.       }
  301.       else {
  302.         if (*argp == ' ' || *argp == '\t') argp++;
  303.         else if (isdigit(*argp)) {
  304.           disk_size = strtol(argp, &argp, 10);
  305.           if (disk_size < 0 || disk_size > 32767)
  306.             syntax("Invalid disk size");
  307.           format_f++;
  308.         }
  309.         else {
  310.           if (drive) syntax("Unrecognised character on command line");
  311.           drive = toupper(*argp++)-'A'+1;
  312.           if (drive < 1 || drive > 'Z'-'A'+1) syntax("Invalid drive");
  313.           if (*argp == ':') argp++;
  314.         }
  315.       }
  316.     }
  317.   }
  318. }
  319.  
  320. /*
  321. **  DOS time format conversions
  322. */
  323.  
  324. unsigned long DOS_time(time_t time)
  325. {
  326.   struct tm *ltime;
  327.   union {
  328.     struct {
  329.       unsigned short sec2 : 5,
  330.                      min : 6,
  331.                      hour : 5;
  332.       unsigned short day : 5,
  333.                      month : 4,
  334.                      year : 7;
  335.     } f;
  336.     unsigned long l;
  337.   } file_time;
  338.  
  339.   ltime = localtime(&time);
  340.   file_time.f.sec2 = ltime->tm_sec;
  341.   file_time.f.min = ltime->tm_min;
  342.   file_time.f.hour = ltime->tm_hour;
  343.   file_time.f.day = ltime->tm_mday;
  344.   file_time.f.month = ltime->tm_mon + 1;
  345.   file_time.f.year = ltime->tm_year - 80;
  346.  
  347.   return file_time.l;
  348. }
  349.  
  350. /*
  351. **  IOCTL messages
  352. */
  353.  
  354. void read_IOCTL_msg(void)
  355. {
  356.   if (ioctl(drive, 4, &IOCTL_msg, sizeof IOCTL_msg) != sizeof IOCTL_msg
  357.   || memcmp(&IOCTL_msg, &IOCTL_msg_hdr, sizeof IOCTL_msg_hdr))
  358.     fatal("Drive not proper ReSizeable RAMDisk");
  359. }
  360.  
  361. int write_IOCTL_msg(void)
  362. {
  363.   if (ioctl(drive, 5, &IOCTL_msg, sizeof (struct IOCTL_msg_s))
  364.       != sizeof (struct IOCTL_msg_s))
  365.   {
  366.     error("Out of memory?");
  367.     return 1;
  368.   }
  369.   return 0;
  370. }
  371.  
  372. void print_IOCTL_msg(void)
  373. {
  374.   int cluster_size = IOCTL_msg.bytes_per_sector * IOCTL_msg.sectors_per_cluster;
  375.   int dir_sectors = IOCTL_msg.dir_entries * 32 / IOCTL_msg.bytes_per_sector;
  376.   int clusters = (IOCTL_msg.sectors - IOCTL_msg.reserved_sectors
  377.     - IOCTL_msg.FAT_sectors * IOCTL_msg.FATs - dir_sectors)
  378.     / IOCTL_msg.sectors_per_cluster;
  379.  
  380.   printf("  Disk size: %iK\n"
  381.          "  Cluster size: %i bytes\n"
  382.          "  Sector size: %i bytes\n"
  383.          "  Directory entries: %i\n"
  384.          "  FAT copies: %i\n"
  385.          "  Bytes available: %li\n"
  386.          "  Write protection: %s\n"
  387.          #ifdef VERBOSE
  388.          "  Sectors: %i\n"
  389.          "  Reserved sectors: %i\n"
  390.          "  FAT sectors: %i\n"
  391.          "  Directory sectors: %i\n"
  392.          "  Sectors per cluster: %i\n"
  393.          "  Clusters: %i\n"
  394.          #endif
  395.          "\n"
  396.          ,IOCTL_msg.disk_size
  397.          ,cluster_size
  398.          ,IOCTL_msg.bytes_per_sector
  399.          ,IOCTL_msg.dir_entries
  400.          ,IOCTL_msg.FATs
  401.          ,(long)clusters*cluster_size
  402.          ,((IOCTL_msg.RW_access & WRITE_ACCESS) ? "OFF" : "ON")
  403.          #ifdef VERBOSE
  404.          ,IOCTL_msg.sectors
  405.          ,IOCTL_msg.reserved_sectors
  406.          ,IOCTL_msg.FAT_sectors
  407.          ,dir_sectors
  408.          ,IOCTL_msg.sectors_per_cluster
  409.          ,clusters
  410.          #endif
  411.          );
  412. }
  413.  
  414. /*
  415. **  Write sectors to disk
  416. **
  417. **  Return 0 for success and 1 for failure
  418. */
  419.  
  420. int write_sector(int count, int start, void *buffer)
  421. {
  422.   if (!IOCTL_msg.IO_entry) fatal("Internal error writing sector");
  423.   _BH = 1;  /* Write */
  424.   _CX = count;
  425.   _DX = start;
  426.   _ES = FP_SEG(buffer);
  427.   _DI = FP_OFF(buffer);
  428.   return IOCTL_msg.IO_entry();
  429. }
  430.  
  431. /*
  432. **  INITIALIZE DRIVE
  433. */
  434.  
  435. void init_drive(void)
  436. {
  437.   read_IOCTL_msg();
  438.  
  439.   if (!force_f) {
  440.     if (IOCTL_msg.disk_size) {
  441.       printf("Current configuration for drive %c:\n\n", drive-1+'A');
  442.       printf("  Usable memory types:");
  443.       if (IOCTL_msg.memory_type & XMS_MEMORY) printf(" XMS");
  444.       if (IOCTL_msg.memory_type & EMS_MEMORY) printf(" EMS");
  445.       if (IOCTL_msg.memory_type & CONV_MEMORY) printf(" conventional");
  446.       if (IOCTL_msg.memory_type & BSW_MEMORY) printf(" BankSwitch");
  447.       if (IOCTL_msg.memory_type & UNKNOWN_MEMORY) printf(" unknown");
  448.       printf("\n");
  449.       print_IOCTL_msg();
  450.     }
  451.     else
  452.       printf("Drive %c: disabled\n\n", drive-1+'A');
  453.   }
  454. }
  455.  
  456. /*
  457. **  SET WRITE PROTECT
  458. */
  459.  
  460. void set_write_protect()
  461. {
  462.   switch(write_f) {
  463.   case set:
  464.     IOCTL_msg.RW_access &= ~WRITE_ACCESS;
  465.     if (!write_IOCTL_msg())
  466.       printf("Write protect enabled\n\n");
  467.     break;
  468.   case clear:
  469.     IOCTL_msg.RW_access |= WRITE_ACCESS;
  470.     if (!write_IOCTL_msg())
  471.       printf("Write protect disabled\n\n");
  472.     break;
  473.   }
  474. }
  475.  
  476. /*
  477. **  FORMAT DISK
  478. */
  479.  
  480. int getYN(void)
  481. {
  482.   int reply;
  483.  
  484.   if (force_f) reply = 'Y';
  485.   else {
  486.     do reply = toupper(getch());
  487.     while (reply != 'Y' && reply != 'N');
  488.   }
  489.   printf("%c\n\n", reply);
  490.   if (reply == 'N') return 0;
  491.   return 1;
  492. }
  493.  
  494. int licence_to_kill(void)
  495. {
  496.   if (!force_f) {
  497.     int reply;
  498.     printf("\aAbout to destroy all files on drive %c!\n\a"
  499.            "Continue (Y/N) ? ", drive-1+'A');
  500.     if (!getYN()) {
  501.       printf("\nOperation aborted\n\n");
  502.       return 0;
  503.     }
  504.   }
  505.   return 1;
  506. }
  507.  
  508. void format_disk(void)
  509. {
  510.   unsigned short old_disk_size = IOCTL_msg.disk_size;
  511.   unsigned short FAT_sectors;
  512.   int FAT_type = 12;    /* By default try to use 12 bit FAT */
  513.   unsigned short data_sectors;
  514.   unsigned short system_sectors;
  515.   unsigned short clusters;
  516.   unsigned short dir_start;
  517.   unsigned short dir_sectors;
  518.   unsigned long sectors;
  519.   ldiv_t ldivr;
  520.   int Fsec;
  521.   int i;
  522.   unsigned char *sector;
  523.  
  524.   if (!force_f && IOCTL_msg.open_files) {
  525.     error("Files open on drive");
  526.     return;
  527.   }
  528.  
  529.   /* Check disk configuration for changes */
  530.   if (disk_size != -1)
  531.     IOCTL_msg.disk_size = disk_size;
  532.  
  533.   if (cluster_size == -1) {
  534.     cluster_size = IOCTL_msg.bytes_per_sector * IOCTL_msg.sectors_per_cluster;
  535.   } else {
  536.     if (cluster_size < IOCTL_msg.bytes_per_sector)
  537.       cluster_size = IOCTL_msg.bytes_per_sector;
  538.     IOCTL_msg.sectors_per_cluster = cluster_size / IOCTL_msg.bytes_per_sector;
  539.   }
  540.  
  541.   if (sector_size != -1)
  542.     IOCTL_msg.bytes_per_sector = sector_size;
  543.  
  544.   if (dir_entries != -1)
  545.     IOCTL_msg.dir_entries = dir_entries;
  546.  
  547.   if (FATs != -1)
  548.     IOCTL_msg.FATs = FATs;
  549.  
  550.   IOCTL_msg.media = media == -1 ? 0xFA : media;
  551.  
  552.  
  553.   /* If Disk will be disabled */
  554.   if (!IOCTL_msg.disk_size) {
  555.     if (!old_disk_size) {
  556.       /* If was disabled also before */
  557.       write_IOCTL_msg();
  558.       printf("New configuration saved for later use\n\n");
  559.     } else {
  560.       /* If disk now get's disabled */
  561.       if (!licence_to_kill()) return;
  562.       IOCTL_msg.RW_access = ~READ_ACCESS & ~WRITE_ACCESS;
  563.       IOCTL_msg.media_change = -1;
  564.       write_IOCTL_msg();
  565.       printf("RAMDisk disabled\n\n");
  566.     }
  567.     return;
  568.   }
  569.  
  570.  
  571.   /* Count the new BPB for disk and see if it can be made */
  572.  
  573.   /* Make sure sectors are big enough for the disk */
  574.   while((sectors = (long)IOCTL_msg.disk_size * 1024
  575.         / IOCTL_msg.bytes_per_sector) > 0xFFFFL)
  576.     IOCTL_msg.bytes_per_sector <<= 1;
  577.  
  578.   IOCTL_msg.sectors = sectors;
  579.   if (cluster_size < IOCTL_msg.bytes_per_sector)
  580.     cluster_size = IOCTL_msg.bytes_per_sector;
  581.  
  582.   { div_t divr;
  583.     divr = div(IOCTL_msg.dir_entries * 32, IOCTL_msg.bytes_per_sector);
  584.     dir_sectors = divr.quot + (divr.rem ? 1 : 0);
  585.   }
  586.  
  587.   count_clusters:
  588.   system_sectors = IOCTL_msg.reserved_sectors + dir_sectors;
  589.   data_sectors = IOCTL_msg.sectors - system_sectors;
  590.  
  591.   IOCTL_msg.sectors_per_cluster = cluster_size / IOCTL_msg.bytes_per_sector;
  592.  
  593.   { ldiv_t divr;
  594.     divr = ldiv(((long)data_sectors + 2 * IOCTL_msg.sectors_per_cluster) * FAT_type,
  595.                 (long)8 * cluster_size + IOCTL_msg.FATs * FAT_type);
  596.     IOCTL_msg.FAT_sectors = divr.quot + (divr.rem ? 1 : 0);
  597.   }
  598.  
  599.   FAT_sectors = IOCTL_msg.FAT_sectors * IOCTL_msg.FATs;
  600.   system_sectors += FAT_sectors;
  601.   data_sectors -= FAT_sectors;
  602.  
  603.   clusters = data_sectors / IOCTL_msg.sectors_per_cluster;
  604.  
  605.   /* Make sure we use the right FAT type */
  606.   if (FAT_type < 16 && clusters > 4077) {
  607.     FAT_type = 16;
  608.     goto count_clusters;
  609.   }
  610.   if (FAT_type > 12 && clusters < 4088 || clusters > 65518) {
  611.     FAT_type = 12;
  612.     cluster_size <<= 1;
  613.     goto count_clusters;
  614.   }
  615.  
  616.   if (IOCTL_msg.sectors <= system_sectors || !clusters)
  617.   {
  618.     error("Impossible format for disk");
  619.     return;
  620.   }
  621.  
  622.   IOCTL_msg.media_change = -1;      /* The media change */
  623.   IOCTL_msg.RW_access = (write_f == set ? 0 : WRITE_ACCESS);
  624.  
  625.   if (!force_f) {
  626.     printf("New disk configuration:\n\n");
  627.     print_IOCTL_msg();
  628.   }
  629.  
  630.   if (old_disk_size && !licence_to_kill()) return;
  631.  
  632.   sector = malloc(IOCTL_msg.bytes_per_sector);
  633.   if (!sector) fatal("Insufficient memory");
  634.  
  635.   /* Enable disk */
  636.   IOCTL_msg.RW_access |= READ_ACCESS;
  637.   /* Request the new disk space by sending the BPB */
  638.   if (write_IOCTL_msg()) return;  /* Return if failed */
  639.  
  640.   /* Write the new disk */
  641.  
  642.   /* Make the boot sector */
  643.   memset(sector, 0, IOCTL_msg.bytes_per_sector);
  644.   memmove(sector, &IOCTL_msg, sizeof IOCTL_msg);
  645.   *(short *)sector = 0x34EB;               /* Boot record JMP instruction */
  646.   *(short *)(sector+24) = sec_per_track;   /* Sectors per track */
  647.   *(short *)(sector+26) = sides;           /* Sides */
  648.   *(short *)(sector+28) = 0;               /* Hidden sectors */
  649.   *(short *)(sector+54) = 0xFEEB;          /* Boot code (JMP $) */
  650.   *(short *)(sector+IOCTL_msg.bytes_per_sector-2) = 0xAA55;  /* Validity code */
  651.   write_sector(1, 0, sector);   /* Write boot sector */
  652.  
  653.   for (i = 0; i < IOCTL_msg.FATs; i++) {
  654.     unsigned short sector_n =
  655.         IOCTL_msg.reserved_sectors + IOCTL_msg.FAT_sectors * i;
  656.     /* Write 1st FAT sector */
  657.     memset(sector, 0, IOCTL_msg.bytes_per_sector);  /* Make 1st FAT sector */
  658.     ((unsigned long *)sector)[0] =
  659.       (FAT_type == 12 ? 0xFFFF00L : 0xFFFFFF00L) | IOCTL_msg.media;
  660.     write_sector(1, sector_n++, sector);
  661.  
  662.     /* Write FAT sectors from 2nd to last */
  663.     ((long *)sector)[0] = 0L;
  664.     for (Fsec = 1; Fsec < IOCTL_msg.FAT_sectors; Fsec++)
  665.         write_sector(1, sector_n++, sector);
  666.   }
  667.  
  668.   /* Write 1st directory sector */
  669.   dir_start = IOCTL_msg.reserved_sectors + FAT_sectors;
  670.   memcpy(sector, IOCTL_msg.volume, 11);
  671.   sector[11] = FA_LABEL;
  672.   *(unsigned long *)(sector+22) = DOS_time(time(NULL));
  673.   write_sector(1, dir_start, sector);
  674.  
  675.   /* Write directory sectors from 2nd to last */
  676.   memset(sector, 0, 16);
  677.   for (Fsec = 1; Fsec < dir_sectors; Fsec++)
  678.       write_sector(1, dir_start+Fsec, sector);
  679.  
  680.   free(sector);
  681.  
  682.   printf("Disk formatted\n\n");
  683. }
  684.  
  685. /*
  686. **  MAIN FUNCTION
  687. */
  688.  
  689. int main(int argc, char *argv[])
  690. {
  691.   printf("ReSizeable RAMDisk Formatter, version "VERSION", "
  692.          "PUBLIC DOMAIN, 1991\n\n");
  693.  
  694.   if (argc > 1) parse_cmdline(argc, argv);
  695.   else printf("For help type 'SRDISK /?'.\n\n");
  696.  
  697.   if (!drive)               /* If no drive specified */
  698.     drive = getdisk()+1;    /* operate on current drive */
  699.  
  700.   init_drive();             /* Get current settings and display it */
  701.  
  702.   if (format_f) format_disk();
  703.   else
  704.     if (write_f != same) set_write_protect();
  705.  
  706.   return 0;
  707. }
  708.